Digital computers process a variety of diverse types of programs, with each program including a series of instructions that enable the processor to perform specific operations in connection with specific elements of data. Typically, particularly in microprocessors designed according to the "RISC" (reduced instruction set computer) architectural model, data to be processed is transferred from, for example, external memory and/or input/output devices, to internal registers. The data in the registers is processed and the processed data is thereafter stored in the registers. At some point, the processed data may be transferred from the registers to the external memory and/or input/output devices for storage or to control the input/output devices. Conventionally in microprocessors designed according to the RISC model, data is transferred between the registers and the external memory and input/output devices using load/store instructions, in particular "load" instructions to load data from the external memory and input/output devices into the microprocessor's registers, and "store" instructions to transfer data in the microprocessor's registers to the external memory and input/output devices for storage. Other instructions, illustratively processing instructions, are used to process the data in the microprocessor's registers.
In performing an external access (that is, a load or store operation in connection with the external memory or the input/output devices) typically a memory management unit will perform checking operations to verify, for example, that the address used to identify the storage location in the external memory or input/output device is a valid address (that is, if the address is within a range of addresses accessible by the program), and that the program attempting to perform the access operation has the right to perform the access operation. Generally, with load instructions, if the memory management unit detects an access violation, which may occur if, for example, the address is invalid or if the program does not have the right to perform the access operation in connection with the location, the memory management unit will provide an "access fault" indication to the microprocessor. The operating system typically maintains a fault handler which, if an access fault is indicated, will typically be called by the microprocessor to, for example, determine the cause of the fault and whether it can be corrected. If the fault handler determines that the fault can be corrected, it may also correct the fault and allow the microprocessor to continue processing the program which issued the faulting instruction. On the other hand, if the fault handler determines that the fault cannot be corrected, the microprocessor may terminate processing of the program which issued the faulting instruction.
Recently, microprocessors have been developed which include "no-fault" facility for use in connection with load instructions to provide some enhanced flexibility in connection with ordering of instructions in a program. Microprocessors which provide a "no-fault" load facility include, for example, those constructed in accordance with the SPARC Version 9 architecture described in SPARC International, Inc David L. Weaver and Tom Germond (eds)!, The SPARC Architecture Manual Version 9 (Prentice-Hall, 1994) (hereinafter referred to as "the SPARC Architecture Manual, Version 9"). During processing of a load instruction in connection with the "no-fault" facility, if the memory management unit detects an access violation, it may provide an access fault indication to the microprocessor. In any case, typically a predetermined value, such as "zero," will be loaded into the register to be loaded and the microprocessor will continue processing the program as if the access violation had not been detected. (A load instruction processed in connection with the "no-fault" facility will be generally referred to herein as a "no-fault load instruction." A no-fault load instruction may comprise an explicit type of instruction specified by the microprocessor's architecture. Alternatively, a no-fault load instruction may be implicitly indicated by one or more elements of a conventional load instruction, as is the case in connection with a microprocessor constructed in accordance with the SPARC Version 9 architecture, by the microprocessor's processing state at the time the load instruction is processed, or by other mechanisms.)
The benefit of a no-fault load instruction will be appreciated from the following. Consider the following Code Segment A:
__________________________________________________________________________ Code Segment A __________________________________________________________________________ (1) comp p, "invalid" ; verify that "p" is a valid address (2) jne "label" ; jump to "label" if "p" is not a valid address (3) ld p!, T ; load contents of location "p" into register T (4) comp T, "a" ; compare contents of "T" to value "a" (5) jne "label2" ; jump to "label2" if contents of "T" do not equal "a" (6) &lt;misc code&gt; ; (7) label &lt;misc code&gt; ; (8) label2 &lt;misc code&gt; ; __________________________________________________________________________
Code Segment A includes, in line (3), a conventional load instruction, that is, a load instruction which is not a no-fault load instruction. In processing of Code Segment A, the microprocessor will first determine whether address "p" is a valid address (line (1)), in the process determining, for example, that the address is within the range of addresses which the program can access. If the microprocessor makes a negative determination during processing of line (1), it will jump (line 2) to code represented by line (7). The code represented in line 7 may comprise additional portions of the program which may be processed if an access fault is detected. Alternatively, the code represented in line (7) may comprise an error handler which is provided by the program which includes Code Segment A to perform selected error recovery operations, such as, for example, determining why "p" was determined to be an invalid address, if possible providing a valid address and resuming processing at line (1), or alternatively terminating processing in a well-behaved manner. On the other hand, if the microprocessor determines in line (1) that "p" is a valid address, it will sequence to line (3) to initiate a load operation to load the data contained in the location identified by address "p" into one of its internal registers, namely register "T." After the load has completed, the microprocessor will compare the contents of register "T" to a value "a" (line 4). If the microprocessor determines in line 4 that the contents of register "T" do not correspond to value "a," it will jump (line 5) to code beginning at line (8). On the other hand, if the microprocessor determines in line 4 that the contents of register "T" correspond to value "a," it will process miscellaneous code represented by line (6).
One problem with the code in Code Segment A is that the load instruction in line (3) may take some time to complete, in which case the microprocessor may be delayed in sequencing to line 4. However, if a conventional load instruction is processed with an invalid address, as described above the operating system's fault handler will be called, which may abruptly terminate of the program containing Code Segment A. To avoid the calling of the operating system's fault handler, the Code Segment A contains the comparison in line (1) and the code represented at line (7).
With a no-fault load instruction, the code in Code Segment A can be rearranged to move the load in line (4) ahead of the compare instruction in line (1), as shown in Code Segment B:
__________________________________________________________________________ Code Segment B __________________________________________________________________________ (1) ld.sub.-- nf p!, T ; no-fault load contents of location "p" into register T (2) comp p, "invalid" ; (3) jne "label" ; (4) comp T, "a" ; (5) jne "label2" ; (6) &lt;misc code&gt; ; (7) label &lt;misc code&gt; ; (8) label2 &lt;misc code&gt; ; __________________________________________________________________________
A benefit of the no-fault load instruction in Code Segment B is that the microprocessor can initiate processing of the load instruction at the beginning of the code segment, several instructions ahead of the comparison in line (4). Since access faults will not be indicated during processing of a no-fault load instruction, if the address "p" is not a valid address the operating system's fault handler will not be called during processing of the no-fault load instruction. However, the microprocessor can verify that the address "p" is a valid address using the comparison on line (2) and if not process the code represented by line (7), which, as described above in connection with Code Segment A, be an error handler which is provided by the program which includes Code Segment B. On the other hand, if the microprocessor determines that the address "p" used in the no-fault load instruction is a valid address, the data should be present in register T earlier in Code Segment B than in Code Segment A, and so the microprocessor should be able to perform the comparison earlier in Code Segment B than in Code Segment A.
One problem that arises with a no-fault load instruction will be described in connection with Code Segment C, as follow:
__________________________________________________________________________ Code Segment C __________________________________________________________________________ (1) ld.sub.-- nf p!, T ; no-fault load contents of location "p" into register T (2) comp p, "invalid" ; (3) jne "label" ; (4) &lt;misc code&gt; ; (5) comp T, "a" ; (6) jne "label2" ; (7) &lt;misc code&gt; ; (8) label &lt;misc code&gt; ; (9) label2 &lt;misc code&gt; ; __________________________________________________________________________
Code Segment C is similar to Code Segment B, except that it includes an additional line (4) that represents "miscellaneous" code to be processed prior to the comparison of the contents of register "T" and value "a" (line 5). If, during processing of the "miscellaneous code" represented by line 4, the microprocessor were to store another value in register "T," before the value that is loaded during processing of the no-fault load instruction is used, then the register "T" will contain an appropriate value for the comparison in line (5) regardless of whether the address "p" used in the no-fault load instruction (line 1) was a valid address. In such a case, the verification (line 2) that the address "p" is a valid address would not be necessary, and the microprocessor would not need to process the error handler code represented by line (8) if address "p" was determined not to be a valid address.